/*
 * =====================================================================================
 *
 *       Filename:  down_stream_request.cc
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2013年06月17日 11时34分27秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Xie Yanping (), 
 *        Company:  www.Qihoo.net
 *
 * =====================================================================================
 */

#include "base/logging.h"
#include "base/url_encode.h"
#include "redis_executor/redis_executor.h"
#include "redis_executor/redis_locator.h"
#include "redis_executor/scoped_reply.h"
#include "down_stream_request.h"
#include "FileTransfer_types.h"
#include "file_trans_redis.h"
#include <boost/format.hpp>

namespace imserver {
namespace fcgi {

bool FileTransDownstreamRequest::Response() {
  LOG_DEBUG("[FileTransDownstreamRequest::Response] called.");
  // read redis-data and fast_cgi it.
  if (!fcgi_out_) {
    LOG_ERROR("Fast-cgi for download stream of file transfer is NULL.");
    return false;
  }

  std::string fcgi_header;
  std::string identify = GetQuery("fid");
  FileContent fc;
  bool success = false;
  int64_t start = 0;

  for (int i = 0; i < 3; ++i) {
    if (0 == FileTransRedis::GetInst().GetFileContent(fc, identify)) {
      LOG_INFO("transfer file with (identify=" << fc.identify
          << ", length=" << fc.content_length
          << ", type=" << fc.content_type << ").");
      if (fc.content_type.find("image") != std::string::npos &&
          GetQuery("download") != "1") {
        fcgi_header = boost::str(boost::format(
              "Content-type: %1%\r\n"
              "Content-Length: %2%\r\n"
              "\r\n") % fc.content_type % fc.content_length);
      } else {
        std::string ua = GetParam("HTTP_USER_AGENT");
        std::string filename = fc.name;
        if (ua.find("MSIE") != std::string::npos){
          filename = base::UrlEncode(fc.name);
        }

        fcgi_header = boost::str(boost::format(
              "Content-type: %1%\r\n"
              "Content-Length: %2%\r\n"
              "Content-disposition: attachment; filename=%3%\r\n"
              "\r\n") % fc.content_type % fc.content_length % filename);
      }

      LOG_DEBUG("fcgi header=" << fcgi_header);
      FCGX_PutS(fcgi_header.c_str(), fcgi_out_);
      success = true;
      break;
    } else {
      LOG_WARN("download stream error.(Get file content failed)");
    }
  }

  if (!success) {
    LOG_DEBUG("pictrue failed.");
    std::string rsp_header(
        "HTTP/1.1 302 Found\r\n"
        "Location: http://imstatic.bang.360.cn/css/img/picfail.png\r\n"
        "Content-type: text/html; charset=utf-8\r\n\r\n");
    FCGX_PutS(rsp_header.c_str(), fcgi_out_);
    std::string rsp_body("http://imstatic.bang.360.cn/css/img/picfail.png");
    FCGX_PutS(rsp_body.c_str(), fcgi_out_);
    return true;
  }

  for (;;) {
    std::string read_stream;
    // format body here.
    if (0 != FileTransRedis::GetInst().GetFileStream(read_stream, identify, start)) {
      LOG_ERROR("Read Redis for file-stream error.(invalid result)");
    } else {
      FCGX_PutStr(read_stream.c_str(), read_stream.size(), fcgi_out_);
      start += read_stream.size();
      if (start >= fc.content_length) {
        LOG_INFO("read file-stream end.");
        return true;
      }
    }

    LOG_DEBUG("current position=" << start);
    usleep(10000);
  }

  return false;
}

}
}
